import uiautomator2 as u2
from concurrent.futures import ThreadPoolExecutor
import service.task.task_service as task_service
import service.info.info_service as info_service
import time
import threading
from rule import task_rule 
import logging
import json
import common.date_utils as date_utils
import action.ws as ws

'''
deviceName
deviceConn
state  -- 0删除 1未连接  2连接中  3在线   4掉线  
recv -- 1正常 2停止（在线但不接受新任务） 3关闭（在线 挂起的任务也不支持）
taskNum -- 任务数量
'''
class CONS():
    STATE_DELETE:int=0
    STATE_UNCONNECT:int=1
    STATE_CONNECTING:int=2
    STATE_ONLINE:int=3
    STATE_UNLINE:int=4

    RECV_START:int=1
    RECV_STOP:int=2
    RECV_CLOSE:int=3

class DeviceActor():

    def __init__(self,deviceName):
        self.limitNum = task_rule.metaData()["limitNum"]
        self.deviceName = deviceName
        self.deviceConn = None
        self.state = CONS.STATE_UNCONNECT
        self.recv = CONS.RECV_START
        self.taskNum = 0
        self.loopThreadPoll = threading.Thread(target=self.loop)
        self.loopThreadPoll.start()

    def connect(self):
        logging.info("%s 连接ADB" %(self.deviceName,))
        self.clearOutCtrlTask()
        self.state = CONS.STATE_CONNECTING
        ws.emit("device")
        try:
            self.deviceConn = u2.connect(self.deviceName)
            self.state = CONS.STATE_ONLINE
        except Exception as e:
            logging.error("%s u2 连接失败 %s" %(self.deviceName,str(e)))
            self.state = CONS.STATE_UNCONNECT
        ws.emit("device")

    def disconnect(self):
        logging.info("%s 断开ADB" %(self.deviceName,))
        self.state = CONS.STATE_UNLINE
        self.deviceConn = None
        ws.emit("device")
    
    def stop(self):
        logging.info("%s 停止" %(self.deviceName,))
        self.recv = CONS.RECV_STOP
        ws.emit("device")

    def close(self):
        logging.info("%s 关闭" %(self.deviceName,))
        self.recv = CONS.RECV_CLOSE
        ws.emit("device")

    def delete(self):
        logging.info("%s 删除" %(self.deviceName,))
        self.state = CONS.STATE_DELETE
        ws.emit("device")

    def loop_handle_newtask(self,stepMetaList):
        ''' 处理新增任务 '''
#        logging.debug("%s 处理新增任务" %(self.deviceName,))
        if self.state == CONS.STATE_ONLINE and self.recv == CONS.RECV_START: #设备可以新增任务 
            taskNum = task_service.countTask(self.deviceName) #当前排行的任务
            if taskNum <= self.limitNum :
                stepMeta0 = stepMetaList[0]
                infoTypes:list = stepMeta0["infoTypes"]
                infoContentList=[]
                task=None

                if infoTypes!=None and len(infoTypes) > 0: #需要资料
                    infoContentList:list = info_service.pops(infoTypes)
                    if len(infoContentList) > 0 : #有资料
                        task = task_service.createTask(self.deviceName)
                    else: #没有资料
                        pass
#                        logging.warning("%s 新建任务缺少资料" %(self.deviceName,))
                else: #不需要资料
                    task = task_service.createTask(self.deviceName)

                if task !=None:
                    taskId=task["id"]
                    try:
                        code,codeText,sleepSec=task_rule.run(self.deviceConn,taskId,0,infoContentList,[])
                        if code == -1:
                            task_service.completeTask(taskId,infoContentList,codeText)
                        else:
                            task_service.suspendTask(taskId,code,sleepSec,infoContentList,codeText)
                    except Exception as e:
                        logging.exception(e)
                        task_service.faultTask(taskId,infoContentList,str(e))

    def loop_handle_suspendtask(self,stepMetaList):
        ''' 处理挂起任务 '''
#        logging.debug("%s 处理挂起任务" %(self.deviceName,))
        if self.state == CONS.STATE_ONLINE and self.recv in [CONS.RECV_START,CONS.RECV_STOP]: #处理暂停的任务
            suspendTaskList = task_service.findSuspendTask(self.deviceName) #暂停的任务
            for suspendTask in suspendTaskList:
                taskId:int=suspendTask["id"]
                step:int = suspendTask["step"]
                stepMetaStep = stepMetaList[step]
                infoTypes:list = stepMetaStep["infoTypes"]
                if infoTypes!=None and len(infoTypes) > 0: #需要资料
                    infoContentList:list = info_service.pops(infoTypes)
                    if len(infoContentList) > 0 : #有资料
                        pass
                    else: #没有资料
                        pass
#                        logging.warning("%s 挂起任务缺少资料" %(self.deviceName,))
                        continue
                try:
                    task_service.activateTask(taskId) #激活任务
                    code,codeText,sleepSec=task_rule.run(self.deviceConn,taskId,step,infoContentList,json.loads(suspendTask["infoContents"]))
                    if code == -1:
                        task_service.completeTask(taskId,infoContentList,codeText)
                    else:
                        task_service.suspendTask(taskId,code,sleepSec,infoContentList,codeText)
                except Exception as e:
                    logging.exception(e)
                    task_service.faultTask(taskId,infoContentList,str(e))

    def loop(self):
        stepMetaList = task_rule.metaData()["steps"]
        if len(stepMetaList) == 0:
            logging.exception("task_rule 没有定义步骤")
        while self.state != CONS.STATE_DELETE :
            beginTime = date_utils.currentTimeMillis() 
            self.loop_handle_newtask(stepMetaList)
            self.loop_handle_suspendtask(stepMetaList)
            endTime = date_utils.currentTimeMillis() 
            useTime = endTime - beginTime
            if useTime < 2000:
                useTime = 2000 - useTime
            time.sleep(useTime / 1000)



    def clearOutCtrlTask(self):
        '''启动时将状态运行中的任务判定为失败'''
        runningTaskList = task_service.findRunningTask(self.deviceName) #暂停的任务
        for runningTask in runningTaskList:
            task_service.faultTask(runningTask["id"],[],"失控的任务")
